home *** CD-ROM | disk | FTP | other *** search
/ Java 1996 August / Java - Summer 1996.iso / kaffe-0.2 / kaffe / classMethod.c < prev    next >
C/C++ Source or Header  |  1996-02-14  |  10KB  |  511 lines

  1. /*
  2.  * classMethod.c
  3.  * Dictionary of classes, methods and fields.
  4.  *
  5.  * Copyright (c) 1996 Systems Architecture Research Centre,
  6.  *           City University, London, UK.
  7.  *
  8.  * See the file "license.terms" for information on usage and redistribution
  9.  * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
  10.  *
  11.  * Written by Tim Wilkinson <tim@sarc.city.ac.uk>, February 1996.
  12.  */
  13.  
  14. #define    CDBG(s)
  15. #define    MDBG(s)
  16. #define    FDBG(s)
  17.  
  18. #include <stdio.h>
  19. #include <assert.h>
  20. #include <string.h>
  21. #include <stdlib.h>
  22. #include "gtypes.h"
  23. #include "constants.h"
  24. #include "classMethod.h"
  25. #include "code.h"
  26. #include "access.h"
  27. #include "readClass.h"
  28. #include "baseClasses.h"
  29. #include "errors.h"
  30.  
  31. extern strpair* initpair;    /* Class init pair <clinit>()V */
  32. extern strpair* finalpair;    /* Class finalize pair finalize()V */
  33. extern classes* classInitHead;
  34. extern int classInitLevel;
  35.  
  36. static classes* classPool[CLASSHASHSZ];
  37. methods* methodList;    /* For exception processing */
  38.  
  39. static classes* internalAddClass(char*, char*, int, char*, classes*, int, constants*);
  40.  
  41. classes*
  42. addClass(constIndex c, constIndex s, u2 flags, constants* pool)
  43. {
  44.     char* str;
  45.     char* sstr;
  46.     classes* cl;
  47.     classes* su;
  48.     int basesize;
  49.     char sig[MAXSIG];
  50.  
  51.     /* Find the name of the class */
  52.     if (pool->tags[c] != CONSTANT_Class) {
  53. CDBG(        printf("addClass: not a class.\n");            )
  54.         return (0);
  55.     }
  56.     c = pool->data[c];
  57.     if (pool->tags[c] != CONSTANT_Utf8) {
  58. CDBG(        printf("addClass: not a Utf8.\n");            )
  59.         return (0);
  60.     }
  61.     str = (uint8*)pool->data[c];
  62.     assert(strlen(str) > 0);
  63.  
  64.     /* Build signature */
  65.     if (str[0] != '[') {
  66.         strcpy(sig, "L");
  67.         strcat(sig, str);
  68.         strcat(sig, ";");
  69.     }
  70.     else {
  71.         strcpy(sig, str);
  72.     }
  73.  
  74.     /* Find the name of the super class */
  75.     if (s != 0) {
  76.         if (pool->tags[s] != CONSTANT_Class) {
  77. CDBG(            printf("addClass: not a class.\n");        )
  78.             return (0);
  79.         }
  80.         s = pool->data[s];
  81.         if (pool->tags[s] != CONSTANT_Utf8) {
  82. CDBG(            printf("addClass: not a Utf8.\n");        )
  83.             return (0);
  84.         }
  85.         sstr = (uint8*)pool->data[s];
  86.         /* Make sure it's loaded in */
  87.         su = lookupClass(sstr);
  88.         if (su == 0) {
  89.             return (0);
  90.         }
  91.         basesize = su->fsize;
  92.     }
  93.     else {
  94.         su = 0;
  95.         basesize = 0;
  96.         sstr = 0;
  97.     }
  98.  
  99. CDBG(    printf("Adding class %s (%x)\n", str, flags);            )
  100.  
  101.     return (internalAddClass(str, addString(sig), flags, sstr, su, basesize, pool));
  102. }
  103.  
  104. classes*
  105. internalAddClass(char* str, char* sig, int flags, char* sstr, classes* su, int basesize, constants* pool)
  106. {
  107.     classes** clp;
  108.     classes* cl;
  109.     methodTable* mt;
  110.     uint32 hash;
  111.     int i;
  112.  
  113.     for (i = 0, hash = 0; str[i] != 0; i++) {
  114.         hash = hash * 33 + str[i];
  115.     }
  116.     hash %= CLASSHASHSZ;
  117.  
  118.     clp = &classPool[hash];
  119. #ifdef DEBUG
  120.     while (*clp != 0) {
  121.         assert(str != (*clp)->name);
  122.         clp = &(*clp)->next;
  123.     }
  124. #endif
  125.  
  126.     /* Allocate a class - it's an object too! */
  127.     cl = alloc_class();
  128.     if (cl == 0) {
  129.         return (0);
  130.     }
  131.     mt = (methodTable*)calloc(sizeof(methodTable), 1);
  132.     if (mt == 0) {
  133.         return (0);
  134.     }
  135.     mt->class = cl;
  136.  
  137.     cl->name = str;
  138.     cl->sig = sig;
  139.     cl->supername = sstr;
  140.     cl->constants = pool;
  141.     cl->methodList = 0;
  142.     cl->fieldList = 0;
  143.     cl->staticFieldList = 0;
  144.     cl->superclass = su;
  145.     cl->fsize = basesize;
  146.     cl->sfsize = 0;
  147.     cl->accflags = flags;
  148.     cl->mtable = mt;
  149.     cl->staticFields = 0;
  150.     cl->interface = 0;
  151.     cl->interface_len = 0;
  152.     cl->state = CSTATE_OK;
  153.     cl->final = false;
  154.     /* Add into list */
  155.     cl->next = *clp;
  156.     *clp = cl;
  157.  
  158.     return (cl);
  159. }
  160.  
  161. methods*
  162. addMethod(classes* c, method_info* m)
  163. {
  164.     constIndex nc;
  165.     constIndex sc;
  166.     methods** mptr;
  167.     methods* mt;
  168.     constants* pool;
  169.     strpair* pair;
  170.  
  171.     pool = c->constants;
  172.  
  173.     nc = m->name_index;
  174.     if (pool->tags[nc] != CONSTANT_Utf8) {
  175. MDBG(        printf("addMethod: no method name.\n");            )
  176.         return (0);
  177.     }
  178.     sc = m->signature_index;
  179.     if (pool->tags[sc] != CONSTANT_Utf8) {
  180. MDBG(        printf("addMethod: no signature name.\n");        )
  181.         return (0);
  182.     }
  183.     pair = addStringConstantPair((char*)pool->data[nc], (char*)pool->data[sc]);
  184.     assert(pair != 0);
  185.  
  186.     /* Mark class for init if this is the class init method */
  187.     if (pair == initpair) {
  188.         c->state = CSTATE_NEEDINIT;
  189.     }
  190.     else if (pair == finalpair) {
  191.         c->final = true;
  192.     }
  193.  
  194.     /* Search down class for method name - don't allow duplicates */
  195.     mptr = &c->methodList;
  196. #ifdef DEBUG
  197.     while (*mptr != 0) {
  198.         assert(pair != (*mptr)->pair);
  199.         mptr = &(*mptr)->next;
  200.     }
  201. #endif
  202.  
  203. MDBG(    printf("Adding method %s:%s%s (%x)\n", c->name, pool->data[nc], pool->data[sc], m->access_flags);    )
  204.  
  205.     mt = (methods*)malloc(sizeof(methods));
  206.     if (mt == 0) {
  207.         return (0);
  208.     }
  209.     mt->pair = pair;
  210.     mt->class = c;
  211.     mt->accflags = m->access_flags;
  212.     mt->code = 0;
  213.     mt->insn = 0;
  214.     mt->ncode = 0;
  215.     mt->constants = pool;
  216.     mt->stacksz = 0;
  217.     mt->localsz = 0;
  218.     mt->exception_table = 0;
  219.     mt->exception_table_len = 0;
  220.     mt->exception_next = 0;
  221.     mt->tableswitches = 0;
  222.     mt->lookupswitches = 0;
  223.     countInsAndOuts((char*)pool->data[sc], &mt->ins, &mt->outs);
  224.     mt->next = *mptr;
  225.     *mptr = mt;
  226.  
  227.     return (mt);
  228. }
  229.  
  230. fields*
  231. addField(classes* c, field_info* f)
  232. {
  233.     constIndex nc;
  234.     constIndex sc;
  235.     fields** fptr;
  236.     fields* ft;
  237.     char* sig;
  238.     constants* pool;
  239.     int* optr;
  240.  
  241.     pool = c->constants;
  242.  
  243.     nc = f->name_index;
  244.     if (pool->tags[nc] != CONSTANT_Utf8) {
  245. FDBG(        printf("addField: no field name.\n");            )
  246.         return (0);
  247.     }
  248.  
  249.     /* Search down class for field name */
  250.     if (f->access_flags & ACC_STATIC) {
  251.         fptr = &c->staticFieldList;
  252.         optr = &c->sfsize;
  253.     }
  254.     else {
  255.         fptr = &c->fieldList;
  256.         optr = &c->fsize;
  257.     }
  258. #ifdef DEBUG
  259.     while (*fptr != 0) {
  260.         assert((char*)pool->data[nc] != (*fptr)->name);
  261.         fptr = &(*fptr)->next;
  262.     }
  263. #endif
  264.  
  265. FDBG(    printf("Adding field %s:%s\n", c->name, pool->data[nc]);    )
  266.  
  267.     sc = f->signature_index;
  268.     if (pool->tags[sc] != CONSTANT_Utf8) {
  269. FDBG(        printf("addField: no signature name.\n");        )
  270.         return (0);
  271.     }
  272.     sig = (char*)pool->data[sc];
  273.  
  274.     ft = (fields*)malloc(sizeof(fields));
  275.     if (ft == 0) {
  276.         return (0);
  277.     }
  278.     ft->name = (char*)pool->data[nc];
  279.     ft->sig = sig;
  280.     ft->class = c;
  281.     ft->accflags = f->access_flags;
  282.     ft->size = sizeofSig(&sig);
  283.     ft->offset = *optr;
  284.     (*optr) += ft->size;
  285.     ft->next = *fptr;
  286.     *fptr = ft;
  287.  
  288.     return (ft);
  289. }
  290.  
  291. void
  292. addMethodCode(methods* m, Code* c)
  293. {
  294.     m->code = c->code;
  295.     m->codelen = c->code_length;
  296.     m->stacksz = c->max_stack;
  297.     m->localsz = c->max_locals;
  298.     m->exception_table = c->exception_table;
  299.     m->exception_table_len = c->exception_table_length;
  300. }
  301.  
  302. void
  303. addInterfaces(classes* c, int inr, classes** inf)
  304. {
  305.     assert(inr > 0);
  306.  
  307.     c->interface = inf;
  308.     c->interface_len = inr;
  309. }
  310.  
  311. /*
  312.  * Lookup a named class, loading it if necessary.
  313.  */
  314. classes*
  315. lookupClass(char* c)
  316. {
  317.     classes* class;
  318.  
  319.     class = simpleLookupClass(c);
  320.     if (class == 0) {
  321.         /* Failed to find class, so must now load it */
  322.         findClass(c);
  323.  
  324.         /* Once loaded, allocate the static data space */
  325.         class = simpleLookupClass(c);
  326.         assert(class != 0);
  327.         if (class->sfsize > 0) {
  328.             class->staticFields = (int*)calloc(class->sfsize, sizeof(int));
  329.             assert(class->staticFields != 0);
  330.         }
  331.     }
  332.     /* This class requires initialisation so place it at head of
  333.        current init list.  If already at head of an init list (not this
  334.        one), then we have a recursive init which is an error */
  335.     if (class->state == CSTATE_OK || class->state == classInitLevel) {
  336.         /* Do nothing. */
  337.     }
  338.     else {
  339.         assert(class->state <= classInitLevel);
  340.         /* If already on a list, remove it */
  341.         if (class->state != CSTATE_NEEDINIT) {
  342.             if (class->prevInit == 0) {
  343.                 throwException(ClassCircularityError);
  344.             }
  345.             class->prevInit->nextInit = class->nextInit;
  346.             if (class->nextInit != 0) {
  347.                 class->nextInit->prevInit = class->prevInit;
  348.             }
  349.         }
  350.         /* Insert onto current list */
  351.         class->state = classInitLevel;
  352.         class->prevInit = 0;
  353.         class->nextInit = classInitHead;
  354.         if (classInitHead) {
  355.             classInitHead->prevInit = class;
  356.         }
  357.         classInitHead = class;
  358.     }
  359.     return (class);
  360. }
  361.  
  362. classes*
  363. simpleLookupClass(char* c)
  364. {
  365.     uint32 hash;
  366.     char* str;
  367.     classes* clp;
  368.  
  369.     for (str = c, hash = 0; *str !=  0; str++) {
  370.         hash = hash * 33 + *str;
  371.     }
  372.     hash %= CLASSHASHSZ;
  373.  
  374.     clp = classPool[hash];
  375.     while (clp != 0) {
  376.         if (c == clp->name) {
  377.             return (clp);
  378.         }
  379.         clp = clp->next;
  380.     }
  381.     return (0);
  382. }
  383.  
  384. /*
  385.  * Lookup a named field.
  386.  */
  387. fields*
  388. lookupClassField(char* c, char* f, bool isStatic)
  389. {
  390.     classes* clp;
  391.     fields* fptr;
  392.  
  393.     /* Look for class */
  394.     clp = lookupClass(c);
  395.     if (clp == 0) {
  396.         return (0);
  397.     }
  398.  
  399.     /* Search down class for field name */
  400.     if (isStatic) {
  401.         fptr = clp->staticFieldList;
  402.     }
  403.     else {
  404.         fptr = clp->fieldList;
  405.     }
  406.     while (fptr != 0) {
  407.         if (f == fptr->name) {
  408.             return (fptr);
  409.         }
  410.         fptr = fptr->next;
  411.     }
  412. FDBG(    printf("Class:field lookup failed %s:%s\n", c, f);        )
  413.     return (0);
  414. }
  415.  
  416. /*
  417.  * Determine the number of arguments and return values from the
  418.  * method signature.
  419.  */
  420. void
  421. countInsAndOuts(char* str, int* ins, int* outs)
  422. {
  423.     *ins = sizeofSig(&str);
  424.     *outs = sizeofSig(&str);
  425. }
  426.  
  427. /*
  428.  * Calculate size of data item based on signature.
  429.  */
  430. int
  431. sizeofSig(char** strp)
  432. {
  433.     int count;
  434.     char* str;
  435.  
  436.     count = 0;
  437.     for (str = *strp; *str != 0; str++) {
  438.         switch (*str) {
  439.         case '(':
  440.             break;
  441.         case ')':
  442.             *strp = str+1;
  443.             return (count);
  444.         case 'I':
  445.         case 'Z':
  446.         case 'S':
  447.         case 'B':
  448.         case 'C':
  449.         case 'F':
  450.             count++;
  451.             break;
  452.         case 'D':
  453.         case 'J':
  454.             count += 2;
  455.             break;
  456.  
  457.         case 'V':
  458.             break;
  459.         case '[':
  460.             count++;
  461.             str++;
  462.             if (*str == 'L') {
  463.                 while (*str != ';') {
  464.                     str++;
  465.                 }
  466.             }
  467.             break;
  468.         case 'L':
  469.             count++;
  470.             /* Skip to end of reference */
  471.             while (*str != ';') {
  472.                 str++;
  473.             }
  474.             break;
  475.         default:
  476.             abort();
  477.         }
  478.     }
  479.     *strp = str;
  480.     return (count);
  481. }
  482.  
  483. /*
  484.  * Add this method to the method list so we can find it when
  485.  * handling exceptions.
  486.  */
  487. void
  488. establishMethod(methods* m)
  489. {
  490.     m->exception_next = methodList;
  491.     methodList = m;
  492. }
  493.  
  494. /*
  495.  * Lookup an array class.
  496.  */
  497. classes*
  498. lookupArray(char* c)
  499. {
  500.     classes* class;
  501.  
  502.     class = simpleLookupClass(c);
  503.     if (class == 0) {
  504.         class = internalAddClass(c, c, 0, 0, 0, 0, 0);
  505. CDBG(        if (class == 0) {
  506.             printf("Array Class %s not loaded.\n", c);
  507.         }                            )
  508.     }
  509.     return (class);
  510. }
  511.